package apiv1

import (
	"gitee.com/bitwormhole/afsviewer/app/classes/fquery"

	"github.com/gin-gonic/gin"
	"github.com/starter-go/afs"
	"github.com/starter-go/libgin"
)

// FqueryController ...
type FqueryController struct {

	//starter:component
	_as func(libgin.Controller) //starter:as(".")

	Sender  libgin.Responder //starter:inject("#")
	Service fquery.Service   //starter:inject("#")
}

func (inst *FqueryController) _impl() libgin.Controller {
	return inst
}

// Registration ...
func (inst *FqueryController) Registration() *libgin.ControllerRegistration {
	return &libgin.ControllerRegistration{Route: inst.route}
}

func (inst *FqueryController) route(rp libgin.RouterProxy) error {

	rp = rp.For("fquery")

	rp.POST("", inst.handlePostQuery)
	rp.GET("", inst.handleGetQuery)
	rp.GET("example", inst.handleGetExample)

	// rp.PUT(":id", inst.handle)
	// rp.DELETE(":id", inst.handle)
	// rp.GET(":id", inst.handleGetOne)

	return nil
}

func (inst *FqueryController) handle(c *gin.Context) {
	req := &myFqueryRequest{
		context:       c,
		controller:    inst,
		wantRequestID: false,
	}
	req.execute(req.doNOP)
}

func (inst *FqueryController) handleGetExample(c *gin.Context) {
	req := &myFqueryRequest{
		context:       c,
		controller:    inst,
		wantRequestID: false,
	}
	req.execute(req.doGetExample)
}

func (inst *FqueryController) handlePostQuery(c *gin.Context) {
	req := &myFqueryRequest{
		context:         c,
		controller:      inst,
		wantRequestBody: true,
	}
	req.execute(req.doPostQuery)
}

func (inst *FqueryController) handleGetQuery(c *gin.Context) {
	req := &myFqueryRequest{
		context:         c,
		controller:      inst,
		wantRequestBody: false,
	}

	driver := c.Query("driver")
	path := c.Query("path")
	if driver != "" {
		path = driver + ":" + path
	}
	uri := "file:///" + path
	req.body1.Query.URI = afs.URI(uri)

	req.execute(req.doPostQuery)
}

////////////////////////////////////////////////////////////////////////////////

type myFqueryRequest struct {
	context    *gin.Context
	controller *FqueryController

	wantRequestID   bool
	wantRequestBody bool

	// id    dxo.FqueryID
	body1 fquery.VO
	body2 fquery.VO
}

func (inst *myFqueryRequest) open() error {

	c := inst.context

	// if inst.wantRequestID {
	// 	idstr := c.Param("id")
	// 	idnum, err := strconv.ParseInt(idstr, 10, 64)
	// 	if err != nil {
	// 		return err
	// 	}
	// 	inst.id = dxo.FqueryID(idnum)
	// }

	if inst.wantRequestBody {
		err := c.BindJSON(&inst.body1)
		if err != nil {
			return err
		}
	}

	return nil
}

func (inst *myFqueryRequest) send(err error) {
	data := &inst.body2
	code := inst.body2.Status
	resp := new(libgin.Response)
	resp.Context = inst.context
	resp.Error = err
	resp.Data = data
	resp.Status = code
	inst.controller.Sender.Send(resp)
}

func (inst *myFqueryRequest) execute(fn func() error) {
	err := inst.open()
	if err == nil {
		err = fn()
	}
	inst.send(err)
}

func (inst *myFqueryRequest) doNOP() error {
	return nil
}

func (inst *myFqueryRequest) doGetExample() error {
	return nil
}

func (inst *myFqueryRequest) doPostQuery() error {
	ctx := inst.context
	ser := inst.controller.Service
	q1 := &inst.body1.Query
	q2, err := ser.Query(ctx, q1)
	if err != nil {
		return err
	}
	inst.body2.Query = *q2
	return nil
}
